package com.hsyt.pfc.support.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Description: 发送HTTP请求基础类，支持POST与GET请求，返回参数格式为JSON
 * @ClassName: HttpUtil
 * @Package: com.hsyt.pfc.imgrpt
 * @Author: wangze@hsyuntai.com
 * @Date: 2016年8月11日 上午9:58:47
 * @Copyright: 版权归 HSYUNTAI 所有
 * <ModifyLog>
 * @ModifyContent:
 * @Author:
 * @Date: </ModifyLog>
 */
public class HttpRequestUtil {

    private static final Log log = LogFactory.getLog(HttpRequestUtil.class);

    private static final Integer RETRY_REQUEST_TIMES = 1;        // 请求失败重试次数
    private static final Integer RETRY_REQUEST_DELAY = 5000;    // 请求失败重试间隔

    /**
     * @param resultJson
     * @param paramName
     * @param clazz
     * @return
     * @Description: 解析返回参数，并将响应JSON字符串转换为clazz类型的对象返回
     * @Author: wangze@hsyuntai.com
     * @Date: 2016年8月12日 上午9:04:53
     */
    public static <T> T getResultBean(String requestType, String url, Map<String, Object> map, Class<T> clazz) {
        String result = doRequest(requestType, url, map);
        try {
            return JSON.parseObject(result, clazz);
        } catch (Exception e) {
            log.info(">>> 返回参数JSON转换异常，待转换类型：" + clazz + " <<<");
        }
        return null;
    }

    /**
     * @param resultJson
     * @param paramName
     * @param clazz
     * @return
     * @Description: 解析返回参数，并将响应JSON字符串转换为clazz类型的对象数组返回
     * @Author: wangze@hsyuntai.com
     * @Date: 2016年8月12日 上午9:06:01
     */
    public static <T> List<T> getResultBeanList(String requestType, String url, Map<String, Object> map, Class<T> clazz) {
        String result = doRequest(requestType, url, map);
        try {
            return JSONArray.parseArray(result, clazz);
        } catch (Exception e) {
            log.info(">>> 返回参数JSON转换异常，待转换类型：" + clazz + " <<<");
        }
        return null;
    }

    /**
     * @param requestType
     * @param url
     * @param map
     * @return
     * @Description: 发送Http POST或者GET请求，并将请求结果返回。
     * @Author: wangze@hsyuntai.com
     * @Date: 2016年8月11日 下午5:04:28
     */
    public static String doRequest(String requestType, String url, Map<String, Object> map) {
        log.info(">>> 接口调用参数 requestType： " + requestType + " <<<");
        log.info(">>> 接口调用参数 url： " + url + " <<<");
        log.info(">>> 接口调用参数 map： " + map + " <<<");
        if (StringUtils.isBlank(url) || StringUtils.isBlank(requestType)) {
            return null;
        }
        String result = "";
        HttpUriRequest request = null;
        if ("POST".equals(requestType.toUpperCase())) {
            request = getHttpPostRequest(url, map);
        } else if ("GET".equals(requestType.toUpperCase())) {
            request = getHttpGetRequest(url, map);
        } else {
            return null;
        }
        result = doHttpRequest(url, request);
        return result;
    }

    /**
     * @param url
     * @param map
     * @return
     * @throws Exception
     * @Description: 发送Http POST或者GET请求，调用失败后会重试，重试RETRY_REQUEST_TIMES次数，每次重试间隔RETRY_REQUEST_DELAY毫秒
     * @Author: wangze@hsyuntai.com
     * @Date: 2016年8月11日 上午10:33:12
     */
    private static String doHttpRequest(String url, HttpUriRequest request) {
        String result = "";
        try {
            HttpClient httpClient = HttpClientBuilder.create().build();
            int i = 0;
            while (i < RETRY_REQUEST_TIMES) {
                HttpResponse response = httpClient.execute(request);
                HttpEntity responseEntity = response.getEntity();
                InputStream inputStream = responseEntity.getContent();
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
                StringBuilder sb = new StringBuilder();
                String line = null;
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }
                result = sb.toString();
                if (!StringUtils.isBlank(result)) {
                    log.info(">>> 接口调用成功： " + url + " <<<");
                    break;
                } else {
                    log.error(">>> 接口调用失败： " + url + " ||| 重试！！！ <<<");
                    Thread.sleep(RETRY_REQUEST_DELAY);
                    i++;
                }
            }
            if (i == RETRY_REQUEST_TIMES) {
                log.error(">>> 接口重试后，调用失败： " + url + " ||| 请排查失败原因！！！ <<<");
            }
        } catch (Exception e) {
            log.error(">>> 接口发生异常： " + url + " ||| 请排查异常！！！ <<<", e);
        }
        log.info(">>> 接口调用返回参数 result： " + result + " <<<");
        return result;
    }

    /**
     * @param url
     * @param map
     * @return
     * @throws Exception
     * @Description: 获取HttpPost请求对象，并将参数放入请求对象中
     * @Author: wangze@hsyuntai.com
     * @Date: 2016年8月11日 上午11:02:20
     */
    private static HttpPost getHttpPostRequest(String url, Map<String, Object> map) {
        HttpPost request = new HttpPost(url);
        if (map == null || map.size() <= 0) {
            return request;
        }
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        for (String key : map.keySet()) {
            nvps.add(new BasicNameValuePair(key, String.valueOf(map.get(key))));
        }
        try {
            request.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
        } catch (UnsupportedEncodingException e) {
            log.error(">>> 参数设置异常，url=： " + url + " ||| map=" + map.toString() + " <<<", e);
        }
        return request;
    }

    /**
     * @param url
     * @param map
     * @return
     * @Description: 获取HttpGet请求对象，并将参数放入请求参数中
     * @Author: wangze@hsyuntai.com
     * @Date: 2016年8月11日 上午11:02:39
     */
    private static HttpGet getHttpGetRequest(String url, Map<String, Object> map) {
        if (map == null || map.size() <= 0) {
            HttpGet request = new HttpGet(url);
            return request;
        }
        String param = "";
        for (String key : map.keySet()) {
            param = key + "=" + String.valueOf(map.get(key)) + "&" + param;
        }
        param = param.substring(0, param.length() - 1);
        if (url.indexOf('?') <= -1) {
            url = url + "?" + param;
        } else {
            url = url + "&" + param;
        }
        log.info(">>> 接口调用参数 url 封装参数后值为： " + url + " <<<");
        HttpGet request = new HttpGet(url);
        return request;
    }

}
